/* eslint-disable react/prop-types */

// Third party dependencies.
import React, {
  useCallback,
  useState,
  useRef,
  useImperativeHandle,
} from 'react';
import { Pressable, TextInput, View } from 'react-native';

// External dependencies.
import { useStyles } from '../../../hooks';
import Input from './foundation/Input';

// Internal dependencies.
import styleSheet from './TextField.styles';
import { TextFieldProps } from './TextField.types';
import {
  DEFAULT_TEXTFIELD_SIZE,
  TOKEN_TEXTFIELD_INPUT_TEXT_VARIANT,
  TEXTFIELD_TEST_ID,
  TEXTFIELD_STARTACCESSORY_TEST_ID,
  TEXTFIELD_ENDACCESSORY_TEST_ID,
} from './TextField.constants';

const TextField = React.forwardRef<TextInput | null, TextFieldProps>(
  (
    {
      style,
      size = DEFAULT_TEXTFIELD_SIZE,
      startAccessory,
      endAccessory,
      isError = false,
      inputElement,
      isDisabled = false,
      autoFocus = false,
      onBlur,
      onFocus,
      testID,
      ...props
    },
    ref,
  ) => {
    const [isFocused, setIsFocused] = useState(autoFocus);
    const inputRef = useRef<TextInput>(null);

    // Expose the input methods to parent components
    useImperativeHandle<TextInput | null, TextInput | null>(
      ref,
      () => inputRef.current,
      [],
    );

    const { styles } = useStyles(styleSheet, {
      style,
      size,
      isError,
      isDisabled,
      isFocused,
    });

    const onBlurHandler = useCallback(
      // TODO: Replace "any" with type
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (e: any) => {
        if (!isDisabled) {
          setIsFocused(false);
          onBlur?.(e);
        }
      },
      [isDisabled, setIsFocused, onBlur],
    );

    const onFocusHandler = useCallback(
      // TODO: Replace "any" with type
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (e: any) => {
        if (!isDisabled) {
          setIsFocused(true);
          onFocus?.(e);
        }
      },
      [isDisabled, setIsFocused, onFocus],
    );

    const onPressHandler = useCallback(() => {
      if (!isDisabled && inputRef.current) {
        inputRef.current.focus();
      }
    }, [isDisabled]);

    return (
      <Pressable
        style={styles.base}
        testID={TEXTFIELD_TEST_ID}
        onPress={onPressHandler}
      >
        {startAccessory && (
          <View
            style={styles.startAccessory}
            testID={TEXTFIELD_STARTACCESSORY_TEST_ID}
          >
            {startAccessory}
          </View>
        )}
        <View style={styles.inputContainer}>
          {inputElement ?? (
            <Input
              textVariant={TOKEN_TEXTFIELD_INPUT_TEXT_VARIANT}
              isDisabled={isDisabled}
              autoFocus={autoFocus}
              onBlur={onBlurHandler}
              onFocus={onFocusHandler}
              testID={testID}
              style={styles.input}
              {...props}
              ref={inputRef}
              isStateStylesDisabled
            />
          )}
        </View>
        {endAccessory && (
          <View
            style={styles.endAccessory}
            testID={TEXTFIELD_ENDACCESSORY_TEST_ID}
          >
            {endAccessory}
          </View>
        )}
      </Pressable>
    );
  },
);

export default TextField;
